﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;

namespace SimpleMapper
{
    /// <summary>
    /// 映射程序
    /// </summary>
    public sealed partial class Mapper
    {
        /// <summary>
        /// 转换方法映射
        /// </summary>
        private static readonly ConcurrentDictionary<int, Delegate> _changeTypeMethodMap = new ConcurrentDictionary<int, Delegate>();

        /// <summary>
        /// 获取一个转换方法
        /// </summary>
        /// <typeparam name="TSource"></typeparam>
        /// <typeparam name="TDestination"></typeparam>
        /// <typeparam name="TFunc"></typeparam>
        /// <param name="changeTypeMethodFactory"></param>
        /// <param name="ignoreInheritProperty"></param>
        /// <param name="sourceRealType"></param>
        /// <returns></returns>
        private static TFunc GetChangeTypeMethod<TSource, TDestination, TFunc>(
            Func<int, Delegate> changeTypeMethodFactory,
            bool? ignoreInheritProperty = null,
            Type sourceRealType = null)
            where TSource : class
            where TDestination : class
            where TFunc : Delegate
        {
            var key = BuildKey<TSource, TDestination>(ignoreInheritProperty, sourceRealType);
            var method = _changeTypeMethodMap.GetOrAdd(key, changeTypeMethodFactory);
            if (method is TFunc func) return func;
            throw new Exception("");
        }
        /// <summary>
        /// 获取给定类型的实例属性
        /// </summary>
        /// <param name="type"></param>
        /// <param name="ignoreInheritProperty"></param>
        /// <returns></returns>
        private static PropertyInfo[] GetProperties(Type type, bool ignoreInheritProperty)
        {
            // 公开的具有setter与getter的实例属性
            var flags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.SetProperty | BindingFlags.GetProperty;
            // 忽略继承而来的属性
            if (ignoreInheritProperty) flags |= BindingFlags.DeclaredOnly;
            var properties = type.GetProperties(flags);
            return properties;
        }
        /// <summary>
        /// 获取属性名称
        /// </summary>
        /// <param name="propertyInfo"></param>
        /// <returns></returns>
        private static string GetPropertyMapName(PropertyInfo propertyInfo)
        {
            if (Attribute.GetCustomAttribute(propertyInfo, typeof(MappingNameAttribute), false) is MappingNameAttribute attribute &&
                !string.IsNullOrEmpty(attribute.Name))
                return attribute.Name;
            return propertyInfo.Name;
        }
        /// <summary>
        /// 根据类型与条件生成缓存key
        /// </summary>
        /// <typeparam name="TSource"></typeparam>
        /// <typeparam name="TDestination"></typeparam>
        /// <param name="ignoreInheritProperty"></param>
        /// <returns></returns>
        private static int BuildKey<TSource, TDestination>(bool? ignoreInheritProperty = null, Type sourceRealType = null)
        {
            var dstType = typeof(TDestination);
            var srcType = sourceRealType ?? typeof(TSource);
            return $"{srcType}{ignoreInheritProperty}{dstType}".GetHashCode();
        }
    }
}
